package service

import (
	"errors"
	"fmt"
	"im/internal/common"
	"im/internal/model"
	"im/internal/socketIO"
	"im/pkg/databases"
	"slices"

	"gorm.io/gorm"
)

type UserSimpleInfo struct {
	Id         int    `json:"id"`
	UserNumber string `json:"user_number"`
	Nickname   string `json:"nickname"`
	Avatar     string `json:"avatar"`
	Bio        string `json:"bio"`
	Status     string `json:"status"`
	Online     bool   `json:"online"`
	Friend     bool   `json:"friend"`
	Block      bool   `json:"block"`
}
type UserWithToken struct {
	model.User
	Token string `json:"token"`
}

func Login(username, password string) (*UserWithToken, error) {
	var user model.User
	result := databases.GetGorm().Where("username = ?", username).Take(&user)
	if errors.Is(result.Error, gorm.ErrRecordNotFound) {
		return nil, errors.New("账号或密码有误")
	} else if result.Error != nil {
		return nil, errors.New(fmt.Sprintf("数据库错误, reason: %s", result.Error.Error()))
	}
	if user.Status != "normal" {
		return nil, errors.New(fmt.Sprintf("账户异常, status: %s", user.Status))
	}
	if common.GetEncryptPassword(password, user.Salt) != user.Password {
		return nil, errors.New("账号或密码有误")
	}
	token := common.RandomUuid()
	if _, err := common.NewToken(token, user.Id, 2592000); err != nil {
		return nil, errors.New("令牌生成失败")
	}
	return &UserWithToken{
		User:  user,
		Token: token,
	}, nil
}

func Search(ownerUserId int, keyword string, exclude []int) ([]UserSimpleInfo, error) {
	var users []model.User
	//先根据user_number查找
	var user model.User
	result := databases.GetGorm().Where("user_number = ? ", keyword).Take(&user)
	if result.Error == nil {
		users = append(users, user)
	}
	//如果user_number未找到则昵称模糊搜索
	if len(users) == 0 {
		databases.GetGorm().Where("nickname LIKE ?", "%"+keyword+"%").Find(&users)
	}
	var infos []UserSimpleInfo
	for _, user := range users {
		if slices.Contains(exclude, user.Id) {
			continue
		}
		search := UserSimpleInfo{
			Id:         user.Id,
			UserNumber: user.UserNumber,
			Nickname:   user.Nickname,
			Avatar:     user.Avatar,
			Bio:        user.Bio,
			Status:     user.Status,
		}
		//判断用户是否在线
		if _, ok := socketIO.UseMap[user.Id]; ok {
			search.Online = true
		}
		search.Friend, _ = IsBothFriend(ownerUserId, user.Id)
		search.Block, _ = IsBlock(ownerUserId, user.Id)
		infos = append(infos, search)
	}
	if len(infos) == 0 {
		return nil, errors.New("未找到用户")
	}
	return infos, nil
}
